μ λ€λ¦ μ λ΅ ν¨ν΄μ΄ μ»΄νμΌ νμ νμ μμ μ±μΌλ‘ μκ³ λ¦¬μ¦ μ νμ κ°ννκ³ , λ°νμ μ€λ₯λ₯Ό λ°©μ§νλ©°, κΈλ‘λ² μ¬μ©μλ₯Ό μν κ°λ ₯νκ³ μ μμ± λμ μννΈμ¨μ΄λ₯Ό ꡬμΆνλ λ°©λ²μ μμ보μΈμ.
μ λ€λ¦ μ λ΅ ν¨ν΄: κ°λ ₯ν κΈλ‘λ² μμ€ν μ μν μκ³ λ¦¬μ¦ μ ν νμ μμ μ± λ³΄μ₯
κ΄λνκ³ μνΈ μ°κ²°λ νλ μννΈμ¨μ΄ κ°λ° νκ²½μμ, μ μ°νκ³ μ μ§λ³΄μ κ°λ₯ν λΏλ§ μλλΌ λ―Ώμ μ μμ μ λλ‘ κ°λ ₯ν μμ€ν μ ꡬμΆνλ κ²μ κ°μ₯ μ€μν©λλ€. μ ν리μΌμ΄μ μ΄ κΈλ‘λ² μ¬μ©μ κΈ°λ°μ μλΉμ€λ₯Ό μ 곡νκ³ , λ€μν λ°μ΄ν°λ₯Ό μ²λ¦¬νλ©°, 무μν λΉμ¦λμ€ κ·μΉμ μ μνλλ‘ νμ₯λ¨μ λ°λΌ, μ°μν μν€ν μ² μ루μ μ λν νμμ±μ λμ± λλ ·ν΄μ§λλ€. κ°μ²΄ μ§ν₯ λμμΈμ μ΄λ¬ν μ΄μ μ€ νλλ μ λ΅ ν¨ν΄(Strategy Pattern)μ λλ€. μ΄λ κ°λ°μκ° μκ³ λ¦¬μ¦ κ°μ‘±μ μ μνκ³ , κ°κ°μ μΊ‘μννλ©°, μνΈ κ΅ν κ°λ₯νκ² λ§λλλ€. νμ§λ§ μκ³ λ¦¬μ¦ μμ²΄κ° λ€μν μ νμ μ λ ₯μ λ€λ£¨κ³ λ€λ₯Έ μ νμ μΆλ ₯μ μμ±ν λλ μ΄λ»κ² λ κΉμ? λ°νμλΏλ§ μλλΌ μ΄μμ μΌλ‘λ μ»΄νμΌ νμμ μ¬λ°λ₯Έ λ°μ΄ν°λ₯Ό κ°μ§ μ¬λ°λ₯Έ μκ³ λ¦¬μ¦μ μ μ©νκ³ μλμ§ μ΄λ»κ² 보μ₯ν μ μμκΉμ?
μ΄ ν¬κ΄μ μΈ κ°μ΄λλ μ ν΅μ μΈ μ λ΅ ν¨ν΄μ μ λ€λ¦(generics)μΌλ‘ κ°ννμ¬ μκ³ λ¦¬μ¦ μ ν νμ μμ μ±μ ν¬κ² ν₯μμν€λ "μ λ€λ¦ μ λ΅ ν¨ν΄"μ λν΄ κΉμ΄ νꡬν©λλ€. μ΄ μ κ·Ό λ°©μμ΄ μ΄λ»κ² μΌλ°μ μΈ λ°νμ μ€λ₯λ₯Ό λ°©μ§ν λΏλ§ μλλΌ, κ΅μ μ μΈ μ΄μμ λ€μν μꡬλ₯Ό μΆ©μ‘±μν¬ μ μλ λ νλ ₯μ μ΄κ³ νμ₯ κ°λ₯νλ©° μ μΈκ³μ μΌλ‘ μ μ κ°λ₯ν μννΈμ¨μ΄ μμ€ν μ μμ±μ μ΄μ§νλμ§ μ΄ν΄λ³Ό κ²μ λλ€.
μ ν΅μ μΈ μ λ΅ ν¨ν΄ μ΄ν΄νκΈ°
μ λ€λ¦μ νμ λν΄ μμ보기 μ μ, μ ν΅μ μΈ μ λ΅ ν¨ν΄μ κ°λ¨ν 볡μ΅ν΄ λ³΄κ² μ΅λλ€. ν΅μ¬μ μΌλ‘, μ λ΅ ν¨ν΄μ λ°νμμ μκ³ λ¦¬μ¦μ μ νν μ μκ² νλ νλ λμμΈ ν¨ν΄μ λλ€. λ¨μΌ μκ³ λ¦¬μ¦μ μ§μ ꡬννλ λμ , ν΄λΌμ΄μΈνΈ ν΄λμ€(컨ν μ€νΈ(Context)λΌκ³ ν¨)λ μκ³ λ¦¬μ¦ κ°μ‘± μ€μμ μ΄λ€ μκ³ λ¦¬μ¦μ μ¬μ©ν μ§μ λν λ°νμ μ§μΉ¨μ λ°μ΅λλ€.
ν΅μ¬ κ°λ λ° λͺ©μ
μ λ΅ ν¨ν΄μ μ£Όμ λͺ©νλ μκ³ λ¦¬μ¦ κ°μ‘±μ μΊ‘μννμ¬ μνΈ κ΅ν κ°λ₯νκ² λ§λλ κ²μ λλ€. μ΄λ₯Ό ν΅ν΄ μκ³ λ¦¬μ¦μ΄ κ·Έκ²μ μ¬μ©νλ ν΄λΌμ΄μΈνΈμ λ 립μ μΌλ‘ λ³κ²½λ μ μμ΅λλ€. μ΄λ¬ν κ΄μ¬μ¬μ λΆλ¦¬λ 컨ν μ€νΈ ν΄λμ€κ° μκ³ λ¦¬μ¦μ΄ μ΄λ»κ² ꡬνλλμ§μ λν ꡬ체μ μΈ λ΄μ©μ μ νμ μμ΄, λ¨μ§ κ·Έ μΈν°νμ΄μ€λ₯Ό μ¬μ©νλ λ°©λ²λ§ μλ©΄ λλ κΉλν μν€ν μ²λ₯Ό μ΄μ§ν©λλ€.
μ ν΅μ μΈ κ΅¬ν ꡬ쑰
μΌλ°μ μΈ κ΅¬νμ μΈ κ°μ§ μ£Όμ κ΅¬μ± μμλ₯Ό ν¬ν¨ν©λλ€:
- μ λ΅ μΈν°νμ΄μ€(Strategy Interface): μ§μλλ λͺ¨λ μκ³ λ¦¬μ¦μ 곡ν΅μ μΈ μΈν°νμ΄μ€λ₯Ό μ μΈν©λλ€. 컨ν μ€νΈλ μ΄ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ κ΅¬μ²΄μ μΈ μ λ΅(ConcreteStrategy)μ μν΄ μ μλ μκ³ λ¦¬μ¦μ νΈμΆν©λλ€.
- ꡬ체μ μΈ μ λ΅(Concrete Strategies): μ λ΅ μΈν°νμ΄μ€λ₯Ό ꡬννμ¬ νΉμ μκ³ λ¦¬μ¦μ μ 곡ν©λλ€.
- 컨ν μ€νΈ(Context): ꡬ체μ μΈ μ λ΅ κ°μ²΄μ λν μ°Έμ‘°λ₯Ό μ μ§νκ³ μ λ΅ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ μκ³ λ¦¬μ¦μ μ€νν©λλ€. 컨ν μ€νΈλ μΌλ°μ μΌλ‘ ν΄λΌμ΄μΈνΈμ μν΄ κ΅¬μ²΄μ μΈ μ λ΅ κ°μ²΄λ‘ ꡬμ±λ©λλ€.
κ°λ μ μμ: λ°μ΄ν° μ λ ¬
λ°μ΄ν°λ₯Ό λ€λ₯Έ λ°©μ(μ: μνλ²³μ, μ«μμ, μμ± λ μ§μ)μΌλ‘ μ λ ¬ν΄μΌ νλ μλ리μ€λ₯Ό μμν΄ λ³΄μΈμ. μ ν΅μ μΈ μ λ΅ ν¨ν΄μ λ€μκ³Ό κ°μ μ μμ΅λλ€:
// μ λ΅ μΈν°νμ΄μ€
interface ISortStrategy {
void Sort(List<DataRecord> data);
}
// ꡬ체μ μΈ μ λ΅ ν΄λμ€
class AlphabeticalSortStrategy : ISortStrategy {
void Sort(List<DataRecord> data) { /* ... μνλ²³μμΌλ‘ μ λ ¬ ... */ }
}
class NumericalSortStrategy : ISortStrategy {
void Sort(List<DataRecord> data) { /* ... μ«μμμΌλ‘ μ λ ¬ ... */ }
}
// 컨ν
μ€νΈ
class DataSorter {
private ISortStrategy _strategy;
public DataSorter(ISortStrategy strategy) {
_strategy = strategy;
}
public void SetStrategy(ISortStrategy strategy) {
_strategy = strategy;
}
public void PerformSort(List<DataRecord> data) {
_strategy.Sort(data);
}
}
μ ν΅μ μΈ μ λ΅ ν¨ν΄μ μ₯μ
μ ν΅μ μΈ μ λ΅ ν¨ν΄μ λͺ κ°μ§ κ°λ ₯ν μ΄μ μ μ 곡ν©λλ€:
- μ μ°μ±: λ°νμμ μκ³ λ¦¬μ¦μ λ체ν μ μμ΄ λμ μΈ νλ λ³κ²½μ΄ κ°λ₯ν©λλ€.
- μ¬μ¬μ©μ±: ꡬ체μ μΈ μ λ΅ ν΄λμ€λ λ€λ₯Έ 컨ν μ€νΈμμ λλ λμΌν 컨ν μ€νΈ λ΄μμ λ€λ₯Έ μμ μ μ¬μ¬μ©λ μ μμ΅λλ€.
- μ μ§λ³΄μμ±: κ° μκ³ λ¦¬μ¦μ μ체 ν΄λμ€μ ν¬ν¨λμ΄ μμ΄ μ μ§λ³΄μ λ° λ 립μ μΈ μμ μ΄ κ°λ¨ν΄μ§λλ€.
- κ°λ°©/νμ μμΉ: ν΄λΌμ΄μΈνΈ μ½λλ₯Ό μμ νμ§ μκ³ λ μλ‘μ΄ μκ³ λ¦¬μ¦μ λμ ν μ μμ΅λλ€.
- μ‘°κ±΄λΆ λ‘μ§ κ°μ: μλ§μ 쑰건문(
if-elseλλswitch)μ λ€νμ λμμΌλ‘ λ체ν©λλ€.
μ ν΅μ μΈ μ κ·Ό λ°©μμ κ³Όμ : νμ μμ μ± κ²©μ°¨
μ ν΅μ μΈ μ λ΅ ν¨ν΄μ κ°λ ₯νμ§λ§, νΉν λ€λ₯Έ λ°μ΄ν° νμ μ λ€λ£¨κ±°λ λ€μν κ²°κ³Όλ₯Ό μμ±νλ μκ³ λ¦¬μ¦μ μ²λ¦¬ν λ νμ μμ μ±κ³Ό κ΄λ ¨νμ¬ νκ³λ₯Ό λλ¬λΌ μ μμ΅λλ€. κ³΅ν΅ μΈν°νμ΄μ€λ μ’ μ’ μ΅μ κ³΅ν΅ λΆλͺ¨ μ κ·Ό λ°©μμ κ°μνκ±°λ μΊμ€ν μ ν¬κ² μμ‘΄νκ² λλλ°, μ΄λ νμ κ²μ¬λ₯Ό μ»΄νμΌ νμμμ λ°νμμΌλ‘ μ΄λμν΅λλ€.
- μ»΄νμΌ νμ νμ μμ μ± λΆμ‘±: κ°μ₯ ν° λ¨μ μ `Strategy` μΈν°νμ΄μ€κ° μ’ μ’ λ§€μ° μΌλ°μ μΈ λ§€κ°λ³μ(μ: `object`, `List
- μλͺ»λ νμ κ°μ μΌλ‘ μΈν λ°νμ μ€λ₯: λ§μ½ `SpecificStrategyA`κ° `InputTypeA`λ₯Ό κΈ°λνμ§λ§ μΌλ°μ μΈ `ISortStrategy` μΈν°νμ΄μ€λ₯Ό ν΅ν΄ `InputTypeB`λ‘ νΈμΆλλ©΄ `ClassCastException`, `InvalidCastException` λλ μ μ¬ν λ°νμ μ€λ₯κ° λ°μν©λλ€. μ΄λ 볡μ‘νκ³ μ μΈκ³μ μΌλ‘ λΆμ°λ μμ€ν μμ λλ²κΉ νκΈ° μ΄λ €μΈ μ μμ΅λλ€.
- λ€μν μ λ΅ μ ν κ΄λ¦¬λ₯Ό μν μμ©κ΅¬(Boilerplate) μ¦κ°: νμ μμ μ± λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ κ°λ°μλ€μ μλ§μ νΉνλ `Strategy` μΈν°νμ΄μ€(μ: `ISortStrategy`, `ITaxCalculationStrategy`, `IAuthenticationStrategy`)λ₯Ό μμ±ν μ μμΌλ©°, μ΄λ μΈν°νμ΄μ€μ κ΄λ ¨ μμ©κ΅¬ μ½λμ νλ°λ‘ μ΄μ΄μ§λλ€.
- 볡μ‘ν μκ³ λ¦¬μ¦ λ³νμ λν νμ₯ μ΄λ €μ: μκ³ λ¦¬μ¦μ μμ νΉμ νμ μꡬμ¬νμ΄ μ¦κ°ν¨μ λ°λΌ, μ λ€λ¦μ΄ μλ μ κ·Ό λ°©μμΌλ‘ μ΄λ¬ν λ³νμ κ΄λ¦¬νλ κ²μ λ²κ±°λ‘κ³ μ€λ₯κ° λ°μνκΈ° μ½μ΅λλ€.
- κΈλ‘λ² μν₯: κΈλ‘λ² μ ν리μΌμ΄μ μμλ λ€λ₯Έ μ§μμ΄λ κ΄ν κΆμ΄ λμΌν λ Όλ¦¬μ μμ (μ: μΈκΈ κ³μ°, λ°μ΄ν° μνΈν νμ€, κ²°μ μ²λ¦¬)μ λν΄ κ·Όλ³Έμ μΌλ‘ λ€λ₯Έ μκ³ λ¦¬μ¦μ μꡬν μ μμ΅λλ€. ν΅μ¬ *μμ *μ λμΌνμ§λ§, κ΄λ ¨λ *λ°μ΄ν° ꡬ쑰*μ *μΆλ ₯*μ λ§€μ° νΉνλ μ μμ΅λλ€. κ°λ ₯ν νμ μμ μ± μμ΄λ μ§μλ³ μκ³ λ¦¬μ¦μ μλͺ» μ μ©νλ©΄ μ¬κ°ν κ·μ μ€μ λ¬Έμ , μ¬μ μ λΆμΌμΉ λλ κ΅μ μ μΈ κ²½κ³λ₯Ό λμ΄ λ°μ΄ν° λ¬΄κ²°μ± λ¬Έμ λ‘ μ΄μ΄μ§ μ μμ΅λλ€.
κΈλ‘λ² μ μμκ±°λ νλ«νΌμ μκ°ν΄ λ΄ μλ€. μ λ½μ λ°°μ‘λΉ κ³μ° μ λ΅μ λ―Έν°λ² λ¨μμ 무κ²μ μΉμλ₯Ό μꡬνκ³ μ λ‘νλ‘ λΉμ©μ μΆλ ₯νλ λ°λ©΄, λΆλ―Έ μ λ΅μ μΌλνμ΄λλ² λ¨μλ₯Ό μ¬μ©νκ³ λ―Έκ΅ λ¬λ¬λ‘ μΆλ ₯ν μ μμ΅λλ€. μ ν΅μ μΈ `ICalculateShippingCost(object orderData)` μΈν°νμ΄μ€λ λ°νμ μ ν¨μ± κ²μ¬ λ° λ³νμ κ°μνμ¬ μ€λ₯ μνμ μ¦κ°μν΅λλ€. λ°λ‘ μ΄ μ§μ μμ μ λ€λ¦μ΄ μ μ€ν νμν ν΄κ²°μ± μ μ 곡ν©λλ€.
μ λ΅ ν¨ν΄μ μ λ€λ¦ λμ νκΈ°
μ λ€λ¦μ μ ν΅μ μΈ μ λ΅ ν¨ν΄μ νμ μμ μ± νκ³λ₯Ό ν΄κ²°νλ κ°λ ₯ν λ©μ»€λμ¦μ μ 곡ν©λλ€. λ©μλ, ν΄λμ€ λ° μΈν°νμ΄μ€ μ μμμ νμ μ λ§€κ°λ³μλ‘ μ¬μ©ν μ μκ² ν¨μΌλ‘μ¨, μ λ€λ¦μ μ»΄νμΌ νμ κ²μ¬λ₯Ό ν¬μνμ§ μμΌλ©΄μλ λ€μν λ°μ΄ν° νμ κ³Ό ν¨κ» μλνλ μ μ°νκ³ μ¬μ¬μ© κ°λ₯νλ©° νμ μμ ν μ½λλ₯Ό μμ±ν μ μκ² ν©λλ€.
μ μ λ€λ¦μΈκ°? νμ μμ μ± λ¬Έμ ν΄κ²°
μ λ€λ¦μ μ°λ¦¬κ° μλνλ νΉμ λ°μ΄ν° νμ κ³Ό λ 립μ μ΄λ©΄μλ μ»΄νμΌ νμμ κ°λ ₯ν νμ κ²μ¬λ₯Ό μ 곡νλ μΈν°νμ΄μ€μ ν΄λμ€λ₯Ό μ€κ³ν μ μκ² ν©λλ€. μ΄λ μ°λ¦¬κ° μ λ΅ μΈν°νμ΄μ€λ₯Ό μ μν λ κ·Έκ²μ΄ κΈ°λνλ μ λ ₯μ *νμ *κ³Ό μμ±ν μΆλ ₯μ *νμ *μ λͺ μμ μΌλ‘ μ μΈν μ μμμ μλ―Έν©λλ€. μ΄λ νμ κ΄λ ¨ λ°νμ μ€λ₯μ κ°λ₯μ±μ κ·Ήμ μΌλ‘ μ€μ΄κ³ μ½λλ² μ΄μ€μ λͺ νμ±κ³Ό κ²¬κ³ μ±μ ν₯μμν΅λλ€.
μ λ€λ¦μ μλ λ°©μ: λ§€κ°λ³μνλ νμ
λ³Έμ§μ μΌλ‘, μ λ€λ¦μ νλ μ΄μ€νλ νμ (νμ λ§€κ°λ³μ)μΌλ‘ ν΄λμ€, μΈν°νμ΄μ€ λ° λ©μλλ₯Ό μ μν μ μκ² ν©λλ€. μ΄λ¬ν μ λ€λ¦ ꡬ쑰λ₯Ό μ¬μ©ν λ, μ΄ νλ μ΄μ€νλμ λν ꡬ체μ μΈ νμ μ μ 곡ν©λλ€. κ·Έλ¬λ©΄ μ»΄νμΌλ¬λ μ΄λ¬ν νμ κ³Ό κ΄λ ¨λ λͺ¨λ μμ μ΄ μ 곡ν ꡬ체μ μΈ νμ κ³Ό μΌμΉνλμ§ νμΈν©λλ€.
μ λ€λ¦ μ λ΅ μΈν°νμ΄μ€
μ λ€λ¦ μ λ΅ ν¨ν΄μ λ§λλ 첫 λ²μ§Έ λ¨κ³λ μ λ€λ¦ μ λ΅ μΈν°νμ΄μ€λ₯Ό μ μνλ κ²μ λλ€. μ΄ μΈν°νμ΄μ€λ μκ³ λ¦¬μ¦μ μ λ ₯ λ° μΆλ ₯μ λν νμ λ§€κ°λ³μλ₯Ό μ μΈν©λλ€.
κ°λ μ μμ:
// μ λ€λ¦ μ λ΅ μΈν°νμ΄μ€
interface IStrategy<TInput, TOutput> {
TOutput Execute(TInput input);
}
μ¬κΈ°μ TInputμ μ λ΅μ΄ λ°κΈ°λ₯Ό κΈ°λνλ λ°μ΄ν°μ νμ
μ λνλ΄κ³ , TOutputμ μ λ΅μ΄ λ°νν κ²μ 보μ₯νλ λ°μ΄ν°μ νμ
μ λνλ
λλ€. μ΄ κ°λ¨ν λ³κ²½μ΄ μμ²λ νμ κ°μ Έμ΅λλ€. μ΄μ μ»΄νμΌλ¬λ μ΄ μΈν°νμ΄μ€λ₯Ό ꡬννλ λͺ¨λ ꡬ체μ μΈ μ λ΅μ΄ μ΄λ¬ν νμ
κ³μ½μ μ€μνλλ‘ κ°μ ν κ²μ
λλ€.
ꡬ체μ μΈ μ λ€λ¦ μ λ΅
μ λ€λ¦ μΈν°νμ΄μ€κ° μ€λΉλλ©΄, μ΄μ μ νν μ λ ₯ λ° μΆλ ₯ νμ μ μ§μ νλ ꡬ체μ μΈ μ λ΅μ μ μν μ μμ΅λλ€. μ΄λ κ° μ λ΅μ μλλ₯Ό λͺ ννκ² νκ³ μ»΄νμΌλ¬κ° κ·Έ μ¬μ©μ κ²μ¦ν μ μκ² ν©λλ€.
μμ: λ€λ₯Έ μ§μμ λν μΈκΈ κ³μ°
μΈκΈμ κ³μ°ν΄μΌ νλ κΈλ‘λ² μ μμκ±°λ μμ€ν μ μκ°ν΄ λ΄ μλ€. μΈκΈ κ·μΉμ κ΅κ°λ³, μ¬μ§μ΄ μ£Ό/λλ³λ‘ ν¬κ² λ€λ¦ λλ€. κ° μ§μμ λν΄ λ€λ₯Έ μ λ ₯ λ°μ΄ν°(μ: νΉμ μΈκΈ μ½λ, μμΉ μΈλΆ μ 보, κ³ κ° μν)μ μ½κ° λ€λ₯Έ μΆλ ₯ νμ(μ: μμΈ λ΄μ, μμ½λ§)μ΄ μμ μ μμ΅λλ€.
μ λ ₯ λ° μΆλ ₯ νμ μ μ:
// 곡ν΅μ±μ μν κΈ°λ³Έ μΈν°νμ΄μ€ (μ ν μ¬ν)
interface IOrderDetails { /* ... κ³΅ν΅ μμ± ... */ }
interface ITaxResult { /* ... κ³΅ν΅ μμ± ... */ }
// λ€λ₯Έ μ§μμ μν νΉμ μ
λ ₯ νμ
class EuropeanOrderDetails : IOrderDetails {
public decimal PreTaxAmount { get; set; }
public string CountryCode { get; set; }
public List<string> VatExemptionCodes { get; set; }
// ... κΈ°ν EU κ΄λ ¨ μΈλΆ μ 보 ...
}
class NorthAmericanOrderDetails : IOrderDetails {
public decimal PreTaxAmount { get; set; }
public string StateProvinceCode { get; set; }
public string ZipPostalCode { get; set; }
// ... κΈ°ν λΆλ―Έ κ΄λ ¨ μΈλΆ μ 보 ...
}
// νΉμ μΆλ ₯ νμ
class EuropeanTaxResult : ITaxResult {
public decimal TotalVAT { get; set; }
public Dictionary<string, decimal> VatBreakdownByRate { get; set; }
public string Currency { get; set; }
}
class NorthAmericanTaxResult : ITaxResult {
public decimal TotalSalesTax { get; set; }
public List<TaxLineItem> LineItemTaxes { get; set; }
public string Currency { get; set; }
}
ꡬ체μ μΈ μ λ€λ¦ μ λ΅:
// μ λ½ λΆκ°κ°μΉμΈ κ³μ° μ λ΅
class EuropeanVatStrategy : IStrategy<EuropeanOrderDetails, EuropeanTaxResult> {
public EuropeanTaxResult Execute(EuropeanOrderDetails order) {
// ... EUμ λν 볡μ‘ν λΆκ°κ°μΉμΈ κ³μ° λ‘μ§ ...
Console.WriteLine($"Calculating EU VAT for {order.CountryCode} on {order.PreTaxAmount}");
return new EuropeanTaxResult { TotalVAT = order.PreTaxAmount * 0.20m, Currency = "EUR" }; // λ¨μνλ μμ
}
}
// λΆλ―Έ νλ§€μΈ κ³μ° μ λ΅
class NorthAmericanSalesTaxStrategy : IStrategy<NorthAmericanOrderDetails, NorthAmericanTaxResult> {
public NorthAmericanTaxResult Execute(NorthAmericanOrderDetails order) {
// ... λΆλ―Έμ λν 볡μ‘ν νλ§€μΈ κ³μ° λ‘μ§ ...
Console.WriteLine($"Calculating NA Sales Tax for {order.StateProvinceCode} on {order.PreTaxAmount}");
return new NorthAmericanTaxResult { TotalSalesTax = order.PreTaxAmount * 0.07m, Currency = "USD" }; // λ¨μνλ μμ
}
}
`EuropeanVatStrategy`λ λ°λμ `EuropeanOrderDetails`λ₯Ό λ°κ³ λ°λμ `EuropeanTaxResult`λ₯Ό λ°νν΄μΌ νλ€λ μ μ μ£Όλͺ©νμΈμ. μ»΄νμΌλ¬κ° μ΄λ₯Ό κ°μ ν©λλ€. λ μ΄μ μ€μλ‘ `NorthAmericanOrderDetails`λ₯Ό EU μ λ΅μ μ λ¬νμ¬ μ»΄νμΌ νμ μ€λ₯λ₯Ό λ°μμν€μ§ μμ΅λλ€.
νμ μ μ½ μ‘°κ±΄ νμ©: μ λ€λ¦μ νμ μ μ½ μ‘°κ±΄(μ: `where TInput : IValidatable`, `where TOutput : class`)κ³Ό κ²°ν©λ λ λμ± κ°λ ₯ν΄μ§λλ€. μ΄λ¬ν μ μ½ μ‘°κ±΄μ `TInput` λ° `TOutput`μ μ 곡λ νμ λ§€κ°λ³μκ° νΉμ μΈν°νμ΄μ€λ₯Ό ꡬννκ±°λ ν΄λμ€μ¬μΌ νλ λ± νΉμ μꡬ μ¬νμ μΆ©μ‘±νλλ‘ λ³΄μ₯ν©λλ€. μ΄λ₯Ό ν΅ν΄ μ λ΅μ μ νν ꡬ체μ μΈ νμ μ μμ§ λͺ»νλλΌλ μ λ ₯/μΆλ ₯μ νΉμ κΈ°λ₯μ κ°μ ν μ μμ΅λλ€.
interface IAuditable {
string GetAuditTrailIdentifier();
}
// κ°μ¬ κ°λ₯ν μ
λ ₯μ μꡬνλ μ λ΅
interface IAuditableStrategy<TInput, TOutput> where TInput : IAuditable {
TOutput Execute(TInput input);
}
class ReportGenerationStrategy<TInput, TOutput> : IAuditableStrategy<TInput, TOutput>
where TInput : IAuditable, IReportParameters // TInputμ Auditableμ΄μ΄μΌ νκ³ Report Parametersλ₯Ό ν¬ν¨ν΄μΌ ν¨
where TOutput : IReportResult, new() // TOutputμ Report Resultμ¬μΌ νκ³ λ§€κ°λ³μ μλ μμ±μλ₯Ό κ°μ ΈμΌ ν¨
{
public TOutput Execute(TInput input) {
Console.WriteLine($"Generating report for audit identifier: {input.GetAuditTrailIdentifier()}");
// ... λ³΄κ³ μ μμ± λ‘μ§ ...
return new TOutput();
}
}
μ΄λ `ReportGenerationStrategy`μ μ 곡λ λͺ¨λ μ λ ₯μ΄ `IAuditable` ꡬνμ κ°λλ‘ λ³΄μ₯νμ¬, μ λ΅μ΄ 리νλ μ μ΄λ λ°νμ νμΈ μμ΄ `GetAuditTrailIdentifier()`λ₯Ό νΈμΆν μ μκ² ν©λλ€. μ΄λ μ²λ¦¬λλ λ°μ΄ν°κ° μ§μλ§λ€ λ€λ₯΄λλΌλ μ μΈκ³μ μΌλ‘ μΌκ΄λ λ‘κΉ λ° κ°μ¬ μμ€ν μ ꡬμΆνλ λ° λ§€μ° μ€μν©λλ€.
μ λ€λ¦ 컨ν μ€νΈ
λ§μ§λ§μΌλ‘, μ΄λ¬ν μ λ€λ¦ μ λ΅μ 보μ νκ³ μ€νν μ μλ 컨ν μ€νΈ ν΄λμ€κ° νμν©λλ€. 컨ν μ€νΈ μ체λ μ λ€λ¦μ΄μ΄μΌ νλ©°, κ΄λ¦¬ν μ λ΅κ³Ό λμΌν `TInput` λ° `TOutput` νμ λ§€κ°λ³μλ₯Ό λ°μμΌ ν©λλ€.
κ°λ μ μμ:
// μ λ€λ¦ μ λ΅ μ»¨ν
μ€νΈ
class StrategyContext<TInput, TOutput> {
private IStrategy<TInput, TOutput> _strategy;
public StrategyContext(IStrategy<TInput, TOutput> strategy) {
_strategy = strategy;
}
public void SetStrategy(IStrategy<TInput, TOutput> strategy) {
_strategy = strategy;
}
public TOutput ExecuteStrategy(TInput input) {
return _strategy.Execute(input);
}
}
μ΄μ `StrategyContext`λ₯Ό μΈμ€ν΄μ€νν λ `TInput`κ³Ό `TOutput`μ λν μ νν νμ μ μ§μ ν΄μΌ ν©λλ€. μ΄λ ν΄λΌμ΄μΈνΈμμ 컨ν μ€νΈλ₯Ό κ±°μ³ κ΅¬μ²΄μ μΈ μ λ΅μ μ΄λ₯΄κΈ°κΉμ§ μμ ν νμ μμ ν νμ΄νλΌμΈμ μμ±ν©λλ€:
// μ λ€λ¦ μΈκΈ κ³μ° μ λ΅ μ¬μ©
// μ λ½μ κ²½μ°:
var euOrder = new EuropeanOrderDetails { PreTaxAmount = 100m, CountryCode = "DE" };
var euStrategy = new EuropeanVatStrategy();
var euContext = new StrategyContext<EuropeanOrderDetails, EuropeanTaxResult>(euStrategy);
EuropeanTaxResult euTax = euContext.ExecuteStrategy(euOrder);
Console.WriteLine($"EU Tax Result: {euTax.TotalVAT} {euTax.Currency}");
// λΆλ―Έμ κ²½μ°:
var naOrder = new NorthAmericanOrderDetails { PreTaxAmount = 100m, StateProvinceCode = "CA", ZipPostalCode = "90210" };
var naStrategy = new NorthAmericanSalesTaxStrategy();
var naContext = new StrategyContext<NorthAmericanOrderDetails, NorthAmericanTaxResult>(naStrategy);
NorthAmericanTaxResult naTax = naContext.ExecuteStrategy(naOrder);
Console.WriteLine($"NA Tax Result: {naTax.TotalSalesTax} {naTax.Currency}");
// 컨ν
μ€νΈμ μλͺ»λ μ λ΅μ μ¬μ©νλ €κ³ μλνλ©΄ μ»΄νμΌ νμ μ€λ₯ λ°μ:
// var wrongContext = new StrategyContext<EuropeanOrderDetails, EuropeanTaxResult>(naStrategy); // μ€λ₯!
λ§μ§λ§ μ€μ ν΅μ¬μ μΈ μ΄μ μ 보μ¬μ€λλ€: μ»΄νμΌλ¬λ `EuropeanOrderDetails`μ `EuropeanTaxResult`λ₯Ό μν΄ κ΅¬μ±λ 컨ν μ€νΈμ `NorthAmericanSalesTaxStrategy`λ₯Ό μ£Όμ νλ €λ μλλ₯Ό μ¦μ ν¬μ°©ν©λλ€. μ΄κ²μ΄ λ°λ‘ μκ³ λ¦¬μ¦ μ ν νμ μμ μ±μ λ³Έμ§μ λλ€.
μκ³ λ¦¬μ¦ μ ν νμ μμ μ± λ¬μ±νκΈ°
μ λ΅ ν¨ν΄μ μ λ€λ¦μ ν΅ν©νλ©΄, μ μ°ν λ°νμ μκ³ λ¦¬μ¦ μ νκΈ°μμ κ°λ ₯νκ³ μ»΄νμΌ νμμ κ²μ¦λλ μν€ν μ² κ΅¬μ± μμλ‘ λ³λͺ¨ν©λλ€. μ΄λ¬ν λ³νλ νΉν 볡μ‘ν κΈλ‘λ² μ ν리μΌμ΄μ μ μ¬μ€ν μ΄μ μ μ 곡ν©λλ€.
μ»΄νμΌ νμ 보μ₯
μ λ€λ¦ μ λ΅ ν¨ν΄μ κ°μ₯ μ€μνκ³ μ£Όλ μ΄μ μ μ»΄νμΌ νμ νμ μμ μ±μ 보μ₯μ λλ€. λ¨ ν μ€μ μ½λλ μ€νλκΈ° μ μ μ»΄νμΌλ¬λ λ€μμ κ²μ¦ν©λλ€:
- `ExecuteStrategy`μ μ λ¬λ `TInput` νμ
μ΄ `IStrategy
` μΈν°νμ΄μ€κ° κΈ°λνλ `TInput` νμ κ³Ό μΌμΉνλμ§. - μ λ΅μ΄ λ°ννλ `TOutput` νμ μ΄ `StrategyContext`λ₯Ό μ¬μ©νλ ν΄λΌμ΄μΈνΈκ° κΈ°λνλ `TOutput` νμ κ³Ό μΌμΉνλμ§.
- 컨ν
μ€νΈμ ν λΉλ λͺ¨λ ꡬ체μ μΈ μ λ΅μ΄ μ§μ λ νμ
μ λν΄ μ λ€λ¦ `IStrategy
` μΈν°νμ΄μ€λ₯Ό μ¬λ°λ₯΄κ² ꡬννλμ§.
μ΄λ λ°νμμ μλͺ»λ νμ κ°μ μΌλ‘ μΈν `InvalidCastException` λλ `NullReferenceException`μ κ°λ₯μ±μ κ·Ήμ μΌλ‘ μ€μ λλ€. λ€λ₯Έ μκ°λμ λ¬Ένμ λ§₯λ½μ κ±Έμ³ λΆμ°λ κ°λ°νμκ², μ΄λ¬ν μΌκ΄λ νμ κ°μ λ κΈ°λλ₯Ό νμ€ννκ³ ν΅ν© μ€λ₯λ₯Ό μ΅μννκΈ° λλ¬Έμ λ§€μ° μ€μν©λλ€.
λ°νμ μ€λ₯ κ°μ
μ»΄νμΌ νμμ νμ λΆμΌμΉλ₯Ό ν¬μ°©ν¨μΌλ‘μ¨, μ λ€λ¦ μ λ΅ ν¨ν΄μ μλΉν μ’ λ₯μ λ°νμ μ€λ₯λ₯Ό κ±°μ μ κ±°ν©λλ€. μ΄λ λ μμ μ μΈ μ ν리μΌμ΄μ , λ μ μ νλ‘λμ μ¬κ³ , κ·Έλ¦¬κ³ λ°°ν¬λ μννΈμ¨μ΄μ λν λ λμ μ λ’°λλ‘ μ΄μ΄μ§λλ€. κΈμ΅ κ±°λ νλ«νΌμ΄λ κΈλ‘λ² μλ£ μ ν리μΌμ΄μ κ³Ό κ°μ λ―Έμ ν¬λ¦¬ν°μ»¬ μμ€ν μ κ²½μ°, λ¨ νλμ νμ κ΄λ ¨ μ€λ₯λ₯Ό λ°©μ§νλ κ²λ§μΌλ‘λ μμ²λ κΈμ μ μν₯μ λ―ΈμΉ μ μμ΅λλ€.
μ½λ κ°λ μ± λ° μ μ§λ³΄μμ± ν₯μ
μ λ΅ μΈν°νμ΄μ€μ ꡬ체μ μΈ ν΄λμ€μμ `TInput`κ³Ό `TOutput`μ λͺ μμ μΌλ‘ μ μΈνλ©΄ μ½λμ μλκ° ν¨μ¬ λ λͺ νν΄μ§λλ€. κ°λ°μλ μκ³ λ¦¬μ¦μ΄ μ΄λ€ μ’ λ₯μ λ°μ΄ν°λ₯Ό κΈ°λνκ³ λ¬΄μμ μμ±ν μ§ μ¦μ μ΄ν΄ν μ μμ΅λλ€. μ΄λ¬ν ν₯μλ κ°λ μ±μ μλ‘μ΄ νμμ μ¨λ³΄λ©μ λ¨μννκ³ , μ½λ 리뷰λ₯Ό κ°μννλ©°, 리ν©ν λ§μ λ μμ νκ² λ§λλλ€. λ€λ₯Έ κ΅κ°μ κ°λ°μλ€μ΄ 곡μ μ½λλ² μ΄μ€μμ νμ ν λ, λͺ νν νμ κ³μ½μ 보νΈμ μΈ μΈμ΄κ° λμ΄ λͺ¨νΈμ±κ³Ό μ€ν΄λ₯Ό μ€μ λλ€.
μμ μλ리μ€: κΈλ‘λ² μ μμκ±°λ νλ«νΌμμμ κ²°μ μ²λ¦¬
λ€μν κ²°μ κ²μ΄νΈμ¨μ΄(μ: PayPal, Stripe, νμ§ μν μ‘κΈ, μ€κ΅μ WeChat Payλ μΌλμ M-Pesaμ κ°μ΄ νΉμ μ§μμμ μΈκΈ° μλ λͺ¨λ°μΌ κ²°μ μμ€ν )μ ν΅ν©ν΄μΌ νλ κΈλ‘λ² μ μμκ±°λ νλ«νΌμ μκ°ν΄ λ΄ μλ€. κ° κ²μ΄νΈμ¨μ΄λ κ³ μ ν μμ² λ° μλ΅ νμμ κ°μ§κ³ μμ΅λλ€.
μ λ ₯/μΆλ ₯ νμ :
// 곡ν΅μ±μ μν κΈ°λ³Έ μΈν°νμ΄μ€
interface IPaymentRequest { string TransactionId { get; set; } /* ... κ³΅ν΅ νλ ... */ }
interface IPaymentResponse { string Status { get; set; } /* ... κ³΅ν΅ νλ ... */ }
// λ€λ₯Έ κ²μ΄νΈμ¨μ΄λ₯Ό μν νΉμ νμ
class StripeChargeRequest : IPaymentRequest {
public string CardToken { get; set; }
public decimal Amount { get; set; }
public string Currency { get; set; }
public Dictionary<string, string> Metadata { get; set; }
}
class PayPalPaymentRequest : IPaymentRequest {
public string PayerId { get; set; }
public string OrderId { get; set; }
public string ReturnUrl { get; set; }
}
class LocalBankTransferRequest : IPaymentRequest {
public string BankName { get; set; }
public string AccountNumber { get; set; }
public string SwiftCode { get; set; }
public string LocalCurrencyAmount { get; set; } // νΉμ νμ§ ν΅ν μ²λ¦¬
}
class StripeChargeResponse : IPaymentResponse {
public string ChargeId { get; set; }
public bool Succeeded { get; set; }
public string FailureCode { get; set; }
}
class PayPalPaymentResponse : IPaymentResponse {
public string PaymentId { get; set; }
public string State { get; set; }
public string ApprovalUrl { get; set; }
}
class LocalBankTransferResponse : IPaymentResponse {
public string ConfirmationCode { get; set; }
public DateTime TransferDate { get; set; }
public string StatusDetails { get; set; }
}
μ λ€λ¦ κ²°μ μ λ΅:
// μ λ€λ¦ κ²°μ μ λ΅ μΈν°νμ΄μ€
interface IPaymentStrategy<TRequest, TResponse> : IStrategy<TRequest, TResponse>
where TRequest : IPaymentRequest
where TResponse : IPaymentResponse
{
// νμνλ€λ©΄ νΉμ κ²°μ κ΄λ ¨ λ©μλλ₯Ό μΆκ°ν μ μμ
}
class StripePaymentStrategy : IPaymentStrategy<StripeChargeRequest, StripeChargeResponse> {
public StripeChargeResponse Execute(StripeChargeRequest request) {
Console.WriteLine($"Processing Stripe charge for {request.Amount} {request.Currency}...");
// ... Stripe APIμ μνΈμμ© ...
return new StripeChargeResponse { ChargeId = "ch_12345", Succeeded = true, Status = "approved" };
}
}
class PayPalPaymentStrategy : IPaymentStrategy<PayPalPaymentRequest, PayPalPaymentResponse> {
public PayPalPaymentResponse Execute(PayPalPaymentRequest request) {
Console.WriteLine($"Initiating PayPal payment for order {request.OrderId}...");
// ... PayPal APIμ μνΈμμ© ...
return new PayPalPaymentResponse { PaymentId = "pay_abcde", State = "created", ApprovalUrl = "http://paypal.com/approve" };
}
}
class LocalBankTransferStrategy : IPaymentStrategy<LocalBankTransferRequest, LocalBankTransferResponse> {
public LocalBankTransferResponse Execute(LocalBankTransferRequest request) {
Console.WriteLine($"Simulating local bank transfer for account {request.AccountNumber} in {request.LocalCurrencyAmount}...");
// ... νμ§ μν API λλ μμ€ν
κ³Ό μνΈμμ© ...
return new LocalBankTransferResponse { ConfirmationCode = "LBT-XYZ", TransferDate = DateTime.UtcNow, Status = "pending", StatusDetails = "Waiting for bank confirmation" };
}
}
μ λ€λ¦ 컨ν μ€νΈμ ν¨κ» μ¬μ©:
// ν΄λΌμ΄μΈνΈ μ½λκ° μ μ ν μ λ΅μ μ ννκ³ μ¬μ©ν¨
// Stripe κ²°μ νλ¦
var stripeRequest = new StripeChargeRequest { Amount = 50.00m, Currency = "USD", CardToken = "tok_visa" };
var stripeStrategy = new StripePaymentStrategy();
var stripeContext = new StrategyContext<StripeChargeRequest, StripeChargeResponse>(stripeStrategy);
StripeChargeResponse stripeResponse = stripeContext.ExecuteStrategy(stripeRequest);
Console.WriteLine($"Stripe Charge Result: {stripeResponse.ChargeId} - {stripeResponse.Succeeded}");
// PayPal κ²°μ νλ¦
var paypalRequest = new PayPalPaymentRequest { OrderId = "ORD-789", PayerId = "payer-abc" };
var paypalStrategy = new PayPalPaymentStrategy();
var paypalContext = new StrategyContext<PayPalPaymentRequest, PayPalPaymentResponse>(paypalStrategy);
PayPalPaymentResponse paypalResponse = paypalContext.ExecuteStrategy(paypalRequest);
Console.WriteLine($"PayPal Payment Status: {paypalResponse.State} - {paypalResponse.ApprovalUrl}");
// νμ§ μν μ‘κΈ νλ¦ (μ: μΈλλ λ
μΌκ³Ό κ°μ νΉμ κ΅κ°)
var localBankRequest = new LocalBankTransferRequest { BankName = "GlobalBank", AccountNumber = "1234567890", SwiftCode = "GBANKXX", LocalCurrencyAmount = "INR 1000" };
var localBankStrategy = new LocalBankTransferStrategy();
var localBankContext = new StrategyContext<LocalBankTransferRequest, LocalBankTransferResponse>(localBankStrategy);
LocalBankTransferResponse localBankResponse = localBankContext.ExecuteStrategy(localBankRequest);
Console.WriteLine($"Local Bank Transfer Confirmation: {localBankResponse.ConfirmationCode} - {localBankResponse.StatusDetails}");
// νΌν©νλ €κ³ νλ©΄ μ»΄νμΌ νμ μ€λ₯ λ°μ:
// var invalidContext = new StrategyContext<StripeChargeRequest, StripeChargeResponse>(paypalStrategy); // μ»΄νμΌλ¬ μ€λ₯!
μ΄ κ°λ ₯ν λΆλ¦¬λ Stripe κ²°μ μ λ΅μ΄ μ€μ§ `StripeChargeRequest`μ ν¨κ» μ¬μ©λκ³ `StripeChargeResponse`λ₯Ό μμ±νλλ‘ λ³΄μ₯ν©λλ€. μ΄λ¬ν κ°λ ₯ν νμ μμ μ±μ μλͺ»λ λ°μ΄ν° λ§€νμ΄ κ±°λ μ€ν¨, μ¬κΈ° λλ κ·μ μ€μ μλ°μΌλ‘ μ΄μ΄μ§ μ μλ κΈλ‘λ² κ²°μ ν΅ν©μ 볡μ‘μ±μ κ΄λ¦¬νλ λ° νμμ μ λλ€.
μμ μλ리μ€: κ΅μ λ°μ΄ν° νμ΄νλΌμΈμ μν λ°μ΄ν° μ ν¨μ± κ²μ¬ λ° λ³ν
μ μΈκ³μ μΌλ‘ μ΄μλλ μ‘°μ§μ μ’ μ’ λ€μν μμ€(μ: λ κ±°μ μμ€ν μ CSV νμΌ, ννΈλμ JSON API, μ°μ νμ€ κΈ°κ΅¬μ XML λ©μμ§)λ‘λΆν° λ°μ΄ν°λ₯Ό μμ§ν©λλ€. κ° λ°μ΄ν° μμ€λ μ²λ¦¬ λ° μ μ₯λκΈ° μ μ νΉμ μ ν¨μ± κ²μ¬ κ·μΉκ³Ό λ³ν λ‘μ§μ μꡬν μ μμ΅λλ€. μ λ€λ¦ μ λ΅μ μ¬μ©νλ©΄ μ μ ν λ°μ΄ν° νμ μ μ¬λ°λ₯Έ μ ν¨μ± κ²μ¬/λ³ν λ‘μ§μ΄ μ μ©λλλ‘ λ³΄μ₯ν μ μμ΅λλ€.
μ λ ₯/μΆλ ₯ νμ :
interface IRawData { string SourceIdentifier { get; set; } }
interface IProcessedData { string ProcessedBy { get; set; } }
class RawCsvData : IRawData {
public string SourceIdentifier { get; set; }
public List<string[]> Rows { get; set; }
public int HeaderCount { get; set; }
}
class RawJsonData : IRawData {
public string SourceIdentifier { get; set; }
public string JsonPayload { get; set; }
public string SchemaVersion { get; set; }
}
class ValidatedCsvData : IProcessedData {
public string ProcessedBy { get; set; }
public List<Dictionary<string, string>> CleanedRecords { get; set; }
public List<string> ValidationErrors { get; set; }
}
class TransformedJsonData : IProcessedData {
public string ProcessedBy { get; set; }
public JObject TransformedPayload { get; set; } // JSON λΌμ΄λΈλ¬λ¦¬μ JObjectλ₯Ό κ°μ
public bool IsValidSchema { get; set; }
}
μ λ€λ¦ μ ν¨μ± κ²μ¬/λ³ν μ λ΅:
interface IDataProcessingStrategy<TInput, TOutput> : IStrategy<TInput, TOutput>
where TInput : IRawData
where TOutput : IProcessedData
{
// μ΄ μμ μμλ μΆκ° λ©μλκ° νμ μμ
}
class CsvValidationTransformationStrategy : IDataProcessingStrategy<RawCsvData, ValidatedCsvData> {
public ValidatedCsvData Execute(RawCsvData rawCsv) {
Console.WriteLine($"Validating and transforming CSV from {rawCsv.SourceIdentifier}...");
// ... 볡μ‘ν CSV νμ±, μ ν¨μ± κ²μ¬, λ³ν λ‘μ§ ...
return new ValidatedCsvData {
ProcessedBy = "CSV_Processor",
CleanedRecords = new List<Dictionary<string, string>>(), // μ μ λ λ°μ΄ν°λ‘ μ±μ
ValidationErrors = new List<string>()
};
}
}
class JsonSchemaTransformationStrategy : IDataProcessingStrategy<RawJsonData, TransformedJsonData> {
public TransformedJsonData Execute(RawJsonData rawJson) {
Console.WriteLine($"Applying schema transformation to JSON from {rawJson.SourceIdentifier}...");
// ... JSON νμ±, μ€ν€λ§ κ²μ¦, λ³ν λ‘μ§ ...
return new TransformedJsonData {
ProcessedBy = "JSON_Processor",
TransformedPayload = new JObject(), // λ³νλ JSONμΌλ‘ μ±μ
IsValidSchema = true
};
}
}
κ·Έλ¬λ©΄ μμ€ν μ `RawCsvData`μ λν΄ `CsvValidationTransformationStrategy`λ₯Ό, `RawJsonData`μ λν΄ `JsonSchemaTransformationStrategy`λ₯Ό μ ννκ² μ ννκ³ μ μ©ν μ μμ΅λλ€. μ΄λ μλ₯Ό λ€μ΄ JSON μ€ν€λ§ μ ν¨μ± κ²μ¬ λ‘μ§μ΄ μ€μλ‘ CSV νμΌμ μ μ©λμ΄ μμΈ‘ κ°λ₯νκ³ μ μν μ»΄νμΌ νμ μ€λ₯λ‘ μ΄μ΄μ§λ μλ리μ€λ₯Ό λ°©μ§ν©λλ€.
κ³ κΈ κ³ λ €μ¬ν λ° κΈλ‘λ² μ μ©
κΈ°λ³Έμ μΈ μ λ€λ¦ μ λ΅ ν¨ν΄μ΄ μλΉν νμ μμ μ± μ΄μ μ μ 곡νμ§λ§, κ³ κΈ κΈ°μ κ³Ό κΈλ‘λ² λ°°ν¬ κ³Όμ λ₯Ό κ³ λ €ν¨μΌλ‘μ¨ κ·Έ νμ λμ± μ¦νμν¬ μ μμ΅λλ€.
μ λ΅ λ±λ‘ λ° κ²μ
μ€μ μ ν리μΌμ΄μ , νΉν λ§μ νΉμ μκ³ λ¦¬μ¦μ κ°μ§ κΈλ‘λ² μμ₯μ μλΉμ€λ₯Ό μ 곡νλ μ ν리μΌμ΄μ μμλ λ¨μν μ λ΅μ `new`λ‘ μμ±νλ κ²λ§μΌλ‘λ μΆ©λΆνμ§ μμ μ μμ΅λλ€. μ¬λ°λ₯Έ μ λ€λ¦ μ λ΅μ λμ μΌλ‘ μ ννκ³ μ£Όμ ν λ°©λ²μ΄ νμν©λλ€. λ°λ‘ μ΄ μ§μ μμ μμ‘΄μ± μ£Όμ (DI) 컨ν μ΄λμ μ λ΅ λ¦¬μ‘Έλ²κ° μ€μν΄μ§λλ€.
- μμ‘΄μ± μ£Όμ
(DI) 컨ν
μ΄λ: λλΆλΆμ νλ μ ν리μΌμ΄μ
μ DI 컨ν
μ΄λ(μ: Javaμ Spring, .NET Coreμ λ΄μ₯ DI, Pythonμ΄λ JavaScript νκ²½μ λ€μν λΌμ΄λΈλ¬λ¦¬)λ₯Ό νμ©ν©λλ€. μ΄ μ»¨ν
μ΄λλ μ λ€λ¦ νμ
μ λ±λ‘μ κ΄λ¦¬ν μ μμ΅λλ€. `IStrategy
`μ μ¬λ¬ ꡬνμ λ±λ‘ν λ€μ λ°νμμ μ μ ν κ²μ ν΄κ²°ν μ μμ΅λλ€. - μ λ€λ¦ μ λ΅ λ¦¬μ‘Έλ²/ν©ν 리: μ¬λ°λ₯Έ μ λ€λ¦ μ λ΅μ λμ μ΄λ©΄μλ νμ
μμ νκ² μ ννλ €λ©΄ 리쑸λ²λ ν©ν 리λ₯Ό λμ
ν μ μμ΅λλ€. μ΄ κ΅¬μ± μμλ νΉμ `TInput` λ° `TOutput` νμ
(μλ§λ λ°νμμ λ©νλ°μ΄ν°λ ꡬμ±μ ν΅ν΄ κ²°μ λ¨)μ λ°μ ν΄λΉ `IStrategy
`λ₯Ό λ°νν©λλ€. *μ ν* λ‘μ§μλ μΌλΆ λ°νμ νμ κ²μ¬(μ: μΌλΆ μΈμ΄μμ `typeof` μ°μ°μλ 리νλ μ μ¬μ©)κ° ν¬ν¨λ μ μμ§λ§, ν΄κ²°λ μ λ΅μ *μ¬μ©*μ 리쑸λ²μ λ°ν νμ μ΄ μμλλ μ λ€λ¦ μΈν°νμ΄μ€μ μΌμΉνκΈ° λλ¬Έμ μ»΄νμΌ νμμ νμ μμ νκ² μ μ§λ©λλ€.
κ°λ μ μ λ΅ λ¦¬μ‘Έλ²:
interface IStrategyResolver {
IStrategy<TInput, TOutput> Resolve<TInput, TOutput>();
}
class DependencyInjectionStrategyResolver : IStrategyResolver {
private readonly IServiceProvider _serviceProvider; // λλ μ΄μ μμνλ DI 컨ν
μ΄λ
public DependencyInjectionStrategyResolver(IServiceProvider serviceProvider) {
_serviceProvider = serviceProvider;
}
public IStrategy<TInput, TOutput> Resolve<TInput, TOutput>() {
// μ΄κ²μ λ¨μνλ μμμ
λλ€. μ€μ DI 컨ν
μ΄λμμλ
// νΉμ IStrategy ꡬνμ λ±λ‘ν©λλ€.
// κ·Έλ° λ€μ DI 컨ν
μ΄λμκ² νΉμ μ λ€λ¦ νμ
μ κ°μ Έμ€λλ‘ μμ²ν©λλ€.
// μ: _serviceProvider.GetService<IStrategy<TInput, TOutput>>();
// λ 볡μ‘ν μλ리μ€μμλ (Type, Type) -> IStrategy λ§€ν λμ
λλ¦¬κ° μμ μ μμ΅λλ€.
// μμ°μ μν΄ μ§μ μ μΈ ν΄κ²°μ κ°μ ν©λλ€.
if (typeof(TInput) == typeof(EuropeanOrderDetails) && typeof(TOutput) == typeof(EuropeanTaxResult)) {
return (IStrategy<TInput, TOutput>)(object)new EuropeanVatStrategy();
}
if (typeof(TInput) == typeof(NorthAmericanOrderDetails) && typeof(TOutput) == typeof(NorthAmericanTaxResult)) {
return (IStrategy<TInput, TOutput>)(object)new NorthAmericanSalesTaxStrategy();
}
throw new InvalidOperationException($"μ
λ ₯ νμ
{typeof(TInput).Name} λ° μΆλ ₯ νμ
{typeof(TOutput).Name}μ λν΄ λ±λ‘λ μ λ΅μ΄ μμ΅λλ€.");
}
}
μ΄ λ¦¬μ‘Έλ² ν¨ν΄μ ν΄λΌμ΄μΈνΈκ° "Xλ₯Ό λ°κ³ Yλ₯Ό λ°ννλ μ λ΅μ΄ νμν©λλ€"λΌκ³ λ§νλ©΄ μμ€ν μ΄ μ΄λ₯Ό μ 곡νλλ‘ ν©λλ€. μΌλ¨ μ 곡λλ©΄, ν΄λΌμ΄μΈνΈλ μμ ν νμ μμ ν λ°©μμΌλ‘ μ΄μ μνΈμμ©ν©λλ€.
νμ μ μ½ μ‘°κ±΄κ³Ό κΈλ‘λ² λ°μ΄ν°μ λν κ·Έ ν
νμ μ μ½ μ‘°κ±΄(`where T : SomeInterface` λλ `where T : SomeBaseClass`)μ κΈλ‘λ² μ ν리μΌμ΄μ μ λ§€μ° κ°λ ₯ν©λλ€. μ΄λ₯Ό ν΅ν΄ μ λ€λ¦ νμ μ체μ νΉμμ±μ ν¬μνμ§ μμΌλ©΄μ λͺ¨λ `TInput` λλ `TOutput` νμ μ΄ κ°μ ΈμΌ νλ κ³΅ν΅ νλμ΄λ μμ±μ μ μν μ μμ΅λλ€.
μμ: μ§μ κ° κ³΅ν΅ κ°μ¬ κ°λ₯μ± μΈν°νμ΄μ€
μ§μμ κ΄κ³μμ΄ λͺ¨λ κΈμ΅ κ±°λ μ λ ₯ λ°μ΄ν°κ° `IAuditableTransaction` μΈν°νμ΄μ€λ₯Ό μ€μν΄μΌ νλ€κ³ μμν΄ λ΄ μλ€. μ΄ μΈν°νμ΄μ€λ `TransactionID`, `Timestamp`, `InitiatorUserID`μ κ°μ κ³΅ν΅ μμ±μ μ μν μ μμ΅λλ€. κ·Έλ° λ€μ νΉμ μ§μ μ λ ₯(μ: `EuroTransactionData`, `YenTransactionData`)μ΄ μ΄ μΈν°νμ΄μ€λ₯Ό ꡬνν©λλ€.
interface IAuditableTransaction {
string GetTransactionIdentifier();
DateTime GetTimestampUtc();
}
class EuroTransactionData : IAuditableTransaction { /* ... */ }
class YenTransactionData : IAuditableTransaction { /* ... */ }
// νΈλμμ
λ‘κΉ
μ μν μ λ€λ¦ μ λ΅
class TransactionLoggingStrategy<TInput, TOutput> : IStrategy<TInput, TOutput>
where TInput : IAuditableTransaction // μ μ½ μ‘°κ±΄μ μ
λ ₯μ΄ κ°μ¬ κ°λ₯ν¨μ 보μ₯ν¨
{
public TOutput Execute(TInput input) {
Console.WriteLine($"Logging transaction: {input.GetTransactionIdentifier()} at {input.GetTimestampUtc()} UTC");
// ... μ€μ λ‘κΉ
λ©μ»€λμ¦ ...
return default(TOutput); // λλ μΌλΆ νΉμ λ‘κ·Έ κ²°κ³Ό νμ
}
}
μ΄λ `TInput`μ΄ `IAuditableTransaction`μΌλ‘ ꡬμ±λ λͺ¨λ μ λ΅μ΄ λ°μ΄ν°κ° μ λ½, μμμ λλ λΆλ―Έμμ λΉλ‘―λμλμ§ μ¬λΆμ κ΄κ³μμ΄ `GetTransactionIdentifier()`μ `GetTimestampUtc()`λ₯Ό μμ μ μΌλ‘ νΈμΆν μ μλλ‘ λ³΄μ₯ν©λλ€. μ΄λ λ€μν κΈλ‘λ² μ΄μ μ λ°μ κ±Έμ³ μΌκ΄λ κ·μ μ€μ λ° κ°μ¬ μΆμ μ ꡬμΆνλ λ° μ€μν©λλ€.
λ€λ₯Έ ν¨ν΄κ³Όμ κ²°ν©
μ λ€λ¦ μ λ΅ ν¨ν΄μ ν₯μλ κΈ°λ₯μ μν΄ λ€λ₯Έ λμμΈ ν¨ν΄κ³Ό ν¨κ³Όμ μΌλ‘ κ²°ν©λ μ μμ΅λλ€:
- ν©ν 리 λ©μλ/μΆμ ν©ν 리: λ°νμ 쑰건(μ: κ΅κ° μ½λ, κ²°μ λ°©λ² μ ν)μ λ°λΌ μ λ€λ¦ μ λ΅μ μΈμ€ν΄μ€λ₯Ό μμ±νκΈ° μν΄. ν©ν 리λ ꡬμ±μ λ°λΌ `IStrategy
`λ₯Ό λ°νν μ μμ΅λλ€. - λ°μ½λ μ΄ν° ν¨ν΄: ν΅μ¬ λ‘μ§μ μμ νμ§ μκ³ μ λ€λ¦ μ λ΅μ ν‘λ¨ κ΄μ¬μ¬(λ‘κΉ
, λ©νΈλ¦, μΊμ±, 보μ κ²μ¬)λ₯Ό μΆκ°νκΈ° μν΄. `LoggingStrategyDecorator
`λ μ€ν μ νμ λ‘κΉ μ μΆκ°νκΈ° μν΄ λͺ¨λ `IStrategy `λ₯Ό κ°μ μ μμ΅λλ€. μ΄λ λ€μν κΈλ‘λ² μκ³ λ¦¬μ¦μ κ±Έμ³ μΌκ΄λ μ΄μ λͺ¨λν°λ§μ μ μ©νλ λ° λ§€μ° μ μ©ν©λλ€.
μ±λ₯μ λ―ΈμΉλ μν₯
λλΆλΆμ νλ νλ‘κ·Έλλ° μΈμ΄μμ μ λ€λ¦ μ¬μ©μ μ±λ₯ μ€λ²ν€λλ λ―Έλ―Έν©λλ€. μ λ€λ¦μ μΌλ°μ μΌλ‘ μ»΄νμΌ νμμ κ° νμ μ λν μ½λλ₯Ό νΉμννκ±°λ(C++ ν νλ¦Ώμ²λΌ) λ°νμ JIT μ»΄νμΌκ³Ό ν¨κ» 곡μ μ λ€λ¦ νμ μ μ¬μ©νμ¬(C#μ΄λ Javaμ²λΌ) ꡬνλ©λλ€. μ΄λ κ²½μ°λ , μ»΄νμΌ νμ νμ μμ μ±, λλ²κΉ κ°μ, λ κΉλν μ½λμ μ±λ₯ μ΄μ μ 무μν μ μλ λ°νμ λΉμ©μ ν¨μ¬ λ₯κ°ν©λλ€.
μ λ€λ¦ μ λ΅μμμ μ€λ₯ μ²λ¦¬
λ€μν μ λ€λ¦ μ λ΅μ κ±Έμ³ μ€λ₯ μ²λ¦¬λ₯Ό νμ€ννλ κ²μ΄ μ€μν©λλ€. μ΄λ λ€μμ ν΅ν΄ λ¬μ±ν μ μμ΅λλ€:
- `TOutput`μ λν κ³΅ν΅ μ€λ₯ μΆλ ₯ νμ λλ μ€λ₯ κΈ°λ³Έ νμ
(μ: `Result
`)μ μ μν©λλ€. - κ° κ΅¬μ²΄μ μΈ μ λ΅ λ΄μμ μΌκ΄λ μμΈ μ²λ¦¬λ₯Ό ꡬννκ³ , μλ§λ νΉμ λΉμ¦λμ€ κ·μΉ μλ°μ ν¬μ°©νμ¬ μ»¨ν μ€νΈλ ν΄λΌμ΄μΈνΈκ° μ²λ¦¬ν μ μλ μ λ€λ¦ `StrategyExecutionException`μΌλ‘ λνν©λλ€.
- λ‘κΉ λ° λͺ¨λν°λ§ νλ μμν¬λ₯Ό νμ©νμ¬ μ€λ₯λ₯Ό μΊ‘μ²νκ³ λΆμνμ¬ λ€λ₯Έ μκ³ λ¦¬μ¦ λ° μ§μμ λν ν΅μ°°λ ₯μ μ 곡ν©λλ€.
μ€μ κΈλ‘λ² νκ²½μμμ μν₯
κ°λ ₯ν νμ μμ μ±μ 보μ₯νλ μ λ€λ¦ μ λ΅ ν¨ν΄μ λ¨μ§ νλ¬Έμ μΈ μ°μ΅μ΄ μλλλ€; μ΄λ κΈλ‘λ² κ·λͺ¨λ‘ μ΄μλλ μ‘°μ§μ μ¬μ€ν μ€μ μ μν₯μ λ―ΈμΉ©λλ€.
κΈμ΅ μλΉμ€: κ·μ μ μ λ° μ€μ
κΈμ΅ κΈ°κ΄μ κ΅κ° λ° μ§μλ³λ‘ λ€μν 볡μ‘ν κ·μ λ§(μ: KYC - κ³ κ° μκΈ°, AML - μκΈ μΈν λ°©μ§, μ λ½μ GDPR, μΊλ¦¬ν¬λμμ CCPA) νμμ μ΄μλ©λλ€. λ€λ₯Έ μ§μμ κ³ κ° μ¨λ³΄λ©, κ±°λ λͺ¨λν°λ§ λλ μ¬κΈ° νμ§λ₯Ό μν΄ λ³κ°μ λ°μ΄ν° ν¬μΈνΈλ₯Ό μꡬν μ μμ΅λλ€. μ λ€λ¦ μ λ΅μ μ΄λ¬ν μ§μλ³ κ·μ μ€μ μκ³ λ¦¬μ¦μ μΊ‘μνν μ μμ΅λλ€:
IKYCVerificationStrategy<CustomerDataEU, EUComplianceReport>IKYCVerificationStrategy<CustomerDataAPAC, APACComplianceReport>
μ΄λ κ³ κ°μ κ΄ν κΆμ λ°λΌ μ¬λ°λ₯Έ κ·μ λ‘μ§μ΄ μ μ©λλλ‘ λ³΄μ₯νμ¬, μ°λ°μ μΈ κ·μ μλ°κ³Ό λ§λν λ²κΈμ λ°©μ§ν©λλ€. λν κ΅μ κ·μ μ€μνμ κ°λ° νλ‘μΈμ€λ₯Ό κ°μνν©λλ€.
μ μμκ±°λ: νμ§νλ μ΄μ λ° κ³ κ° κ²½ν
κΈλ‘λ² μ μμκ±°λ νλ«νΌμ λ€μν κ³ κ° κΈ°λμ μ΄μ μꡬ μ¬νμ μΆ©μ‘±ν΄μΌ ν©λλ€:
- νμ§νλ κ°κ²© μ± μ λ° ν μΈ: λμ κ°κ²© μ± μ , μ§μλ³ νλ§€μΈ μ μ©(VAT λ νλ§€μΈ), λλ νμ§ νλ‘λͺ¨μ μ λ§μΆ ν μΈ μ 곡μ μν μ λ΅.
- λ°°μ‘λΉ κ³μ°: λ€λ₯Έ λ¬Όλ₯ μ 곡μ 체, λ°°μ‘ μ§μ, μΈκ΄ κ·μ μ λ€μν λ°°μ‘λΉ μκ³ λ¦¬μ¦μ νμλ‘ ν©λλ€.
- κ²°μ κ²μ΄νΈμ¨μ΄: μμμμ 보μλ―μ΄, κ³ μ ν λ°μ΄ν° νμμ κ°μ§ κ΅κ°λ³ κ²°μ λ°©λ²μ μ§μν©λλ€.
- μ¬κ³ κ΄λ¦¬: μ§μλ³ μμ λ° μ°½κ³ μμΉμ λ°λΌ μ¬κ³ ν λΉ λ° μ²λ¦¬λ₯Ό μ΅μ ννλ μ λ΅.
μ λ€λ¦ μ λ΅μ μ΄λ¬ν νμ§νλ μκ³ λ¦¬μ¦μ΄ μ μ νκ³ νμ μμ ν λ°μ΄ν°λ‘ μ€νλλλ‘ λ³΄μ₯νμ¬, κ³μ° μ°©μ€, λΆμ νν μ²κ΅¬, κ·Έλ¦¬κ³ κΆκ·Ήμ μΌλ‘λ λμ κ³ κ° κ²½νμ λ°©μ§ν©λλ€.
μλ£: λ°μ΄ν° μνΈμ΄μ©μ± λ° κ°μΈμ 보 보νΈ
μλ£ μ°μ μ λ€μν νμ€κ³Ό μ격ν κ°μΈμ 보 보νΈλ²(μ: λ―Έκ΅μ HIPAA, μ λ½μ GDPR, νΉμ κ΅κ° κ·μ )μ λ°λΌ λ°μ΄ν° κ΅νμ ν¬κ² μμ‘΄ν©λλ€. μ λ€λ¦ μ λ΅μ λ§€μ° μ μ©ν μ μμ΅λλ€:
- λ°μ΄ν° λ³ν: λ°μ΄ν° 무결μ±μ μ μ§νλ©΄μ λ€λ₯Έ κ±΄κ° κΈ°λ‘ νμ(μ: HL7, FHIR, κ΅κ°λ³ νμ€) κ°μ λ³ννλ μκ³ λ¦¬μ¦.
- νμ λ°μ΄ν° μ΅λͺ ν: μ°κ΅¬λ λΆμμ μν΄ κ³΅μ νκΈ° μ μ νμ λ°μ΄ν°μ μ§μλ³ μ΅λͺ ν λλ κ°λͺ ν κΈ°μ μ μ μ©νλ μ λ΅.
- μμ κ²°μ μ§μ: μ§λ³ μ§λ¨μ΄λ μΉλ£ κΆμ₯ μ¬νμ μν μκ³ λ¦¬μ¦, μ΄λ μ§μλ³ μν λ°μ΄ν°λ μμ μ§μΉ¨μΌλ‘ λ―ΈμΈ μ‘°μ λ μ μμ΅λλ€.
μ¬κΈ°μμ νμ μμ μ±μ λ¨μ§ μ€λ₯λ₯Ό λ°©μ§νλ κ²μ κ·ΈμΉμ§ μκ³ , λ―Όκ°ν νμ λ°μ΄ν°κ° μ격ν νλ‘ν μ½μ λ°λΌ μ²λ¦¬λλλ‘ λ³΄μ₯νλ κ²μΌλ‘, μ΄λ μ μΈκ³μ μΌλ‘ λ²μ λ° μ€λ¦¬μ μ€μμ μ€μν©λλ€.
λ°μ΄ν° μ²λ¦¬ λ° λΆμ: λ€μ€ νμ, λ€μ€ μμ€ λ°μ΄ν° μ²λ¦¬
λκΈ°μ μ μ’ μ’ κΈλ‘λ² μ΄μμμ λ€μν νμκ³Ό λ€μν μμ€ν μμ λ°©λν μμ λ°μ΄ν°λ₯Ό μμ§ν©λλ€. μ΄ λ°μ΄ν°λ λΆμ νλ«νΌμ λ‘λλκΈ° μ μ μ ν¨μ±μ κ²μ¬νκ³ , λ³ννκ³ , λ‘λν΄μΌ ν©λλ€.
- ETL (μΆμΆ, λ³ν, λ‘λ) νμ΄νλΌμΈ: μ λ€λ¦ μ λ΅μ λ€μ΄μ€λ λ€λ₯Έ λ°μ΄ν° μ€νΈλ¦Όμ λν νΉμ λ³ν κ·μΉμ μ μν μ μμ΅λλ€ (μ: `TransformCsvStrategy
`, `TransformJsonStrategy `). - λ°μ΄ν° νμ§ κ²μ¬: μ§μλ³ λ°μ΄ν° μ ν¨μ± κ²μ¬ κ·μΉ(μ: μ°νΈ λ²νΈ, κ΅κ° μλ³ λ²νΈ λλ ν΅ν νμ κ²μ¦)μ μΊ‘μνν μ μμ΅λλ€.
μ΄ μ κ·Ό λ°©μμ λ°μ΄ν° λ³ν νμ΄νλΌμΈμ΄ κ°λ ₯νκ³ , μ΄μ§μ μΈ λ°μ΄ν°λ₯Ό μ λ°νκ² μ²λ¦¬νλ©°, λΉμ¦λμ€ μΈν 리μ μ€μ μ μΈκ³μ μΈ μμ¬ κ²°μ μ μν₯μ λ―ΈμΉ μ μλ λ°μ΄ν° μμμ λ°©μ§ν¨μ 보μ₯ν©λλ€.
νμ μμ μ±μ΄ μ μΈκ³μ μΌλ‘ μ€μν μ΄μ
κΈλ‘λ² λ§₯λ½μμ νμ μμ μ±μ μ€μμ±μ λμ± λμμ§λλ€. λ‘컬 μ ν리μΌμ΄μ μμ μ¬μν λ²κ·ΈμΌ μ μλ νμ λΆμΌμΉλ λλ₯μ κ°λ‘μ§λ¬ μ΄μλλ μμ€ν μμ μΉλͺ μ μΈ μ€ν¨κ° λ μ μμ΅λλ€. μ΄λ λ€μμΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€:
- μ¬μ μ μμ€: λΆμ νν μΈκΈ κ³μ°, κ²°μ μ€ν¨ λλ μλͺ»λ κ°κ²© μ± μ μκ³ λ¦¬μ¦.
- κ·μ μ€μ μ€ν¨: λ°μ΄ν° κ°μΈμ 보 보νΈλ², κ·μ λͺ λ Ή λλ μ°μ νμ€ μλ°.
- λ°μ΄ν° μμ: λ°μ΄ν°λ₯Ό λΆμ ννκ² μμ§νκ±°λ λ³ννμ¬ μ λ’°ν μ μλ λΆμκ³Ό μλͺ»λ λΉμ¦λμ€ κ²°μ μΌλ‘ μ΄μ΄μ§.
- νν μμ: λ€λ₯Έ μ§μμ κ³ κ°μκ² μν₯μ λ―ΈμΉλ μμ€ν μ€λ₯λ κΈλ‘λ² λΈλλμ λν μ λ’°λ₯Ό λΉ λ₯΄κ² μ½νμν¬ μ μμ΅λλ€.
μ»΄νμΌ νμ νμ μμ μ±μ κ°μΆ μ λ€λ¦ μ λ΅ ν¨ν΄μ μ€μν λ³΄νΈ μ₯μΉ μν μ νμ¬, κΈλ‘λ² μ΄μμ νμν λ€μν μκ³ λ¦¬μ¦μ΄ μ¬λ°λ₯΄κ³ μμ μ μΌλ‘ μ μ©λλλ‘ λ³΄μ₯νλ©°, μ 체 μννΈμ¨μ΄ μνκ³μ κ±Έμ³ μΌκ΄μ±κ³Ό μμΈ‘ κ°λ₯μ±μ μ‘°μ±ν©λλ€.
ꡬν λͺ¨λ² μ¬λ‘
μ λ€λ¦ μ λ΅ ν¨ν΄μ μ΄μ μ κ·Ήλννλ €λ©΄ ꡬν μ€μ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό κ³ λ €νμμμ€:
- μ λ΅μ μ§μ€μ μΌλ‘ μ μ§ (λ¨μΌ μ± μ μμΉ): κ° κ΅¬μ²΄μ μΈ μ λ€λ¦ μ λ΅μ λ¨μΌ μκ³ λ¦¬μ¦μ μ± μμ ΈμΌ ν©λλ€. μ¬λ¬ κ΄λ ¨ μλ μμ μ νλμ μ λ΅μ κ²°ν©νμ§ λ§μμμ€. μ΄λ νΉν νμ μ μΈ κΈλ‘λ² κ°λ° νκ²½μμ μ½λλ₯Ό κΉ¨λνκ³ , ν μ€νΈ κ°λ₯νλ©°, μ΄ν΄νκΈ° μ½κ² μ μ§ν©λλ€.
- λͺ νν λͺ λͺ κ·μΉ: μΌκ΄λκ³ μ€λͺ μ μΈ λͺ λͺ κ·μΉμ μ¬μ©νμμμ€. μλ₯Ό λ€μ΄, `Generic<TInput, TOutput>Strategy`, `PaymentProcessingStrategy<StripeRequest, StripeResponse>`, `TaxCalculationContext<OrderData, TaxResult>`. λͺ νν μ΄λ¦μ λ€λ₯Έ μΈμ΄μ λ°°κ²½μ κ°μ§ κ°λ°μλ€μ λͺ¨νΈμ±μ μ€μ λλ€.
- μ² μ ν ν μ€νΈ: κ° κ΅¬μ²΄μ μΈ μ λ€λ¦ μ λ΅μ λν΄ ν¬κ΄μ μΈ λ¨μ ν μ€νΈλ₯Ό ꡬννμ¬ μκ³ λ¦¬μ¦μ μ νμ±μ κ²μ¦νμμμ€. λν, μ λ΅ μ ν λ‘μ§(μ: `IStrategyResolver`)κ³Ό `StrategyContext`μ λν ν΅ν© ν μ€νΈλ₯Ό μμ±νμ¬ μ 체 νλ¦μ΄ κ²¬κ³ νμ§ νμΈνμμμ€. μ΄λ λΆμ°λ ν μ λ°μ κ±Έμ³ νμ§μ μ μ§νλ λ° μ€μν©λλ€.
- λ¬Έμν: μ λ€λ¦ λ§€κ°λ³μ(`TInput`, `TOutput`), λͺ¨λ νμ μ μ½ μ‘°κ±΄, κ·Έλ¦¬κ³ κ° μ λ΅μ μμλλ λμμ λͺ©μ μ λͺ ννκ² λ¬Έμννμμμ€. μ΄ λ¬Έμλ κΈλ‘λ² κ°λ°νμκ² μ€μν μμμ΄ λμ΄ μ½λλ² μ΄μ€μ λν 곡μ λ μ΄ν΄λ₯Ό 보μ₯ν©λλ€.
- λμμ€ κ³ λ € β κ³Όλν μμ§λμ΄λ§ λ°©μ§: μ λ€λ¦ μ λ΅ ν¨ν΄μ΄ κ°λ ₯νμ§λ§ λͺ¨λ λ¬Έμ μ λν λ§λ³ν΅μΉμ½μ μλλλ€. λͺ¨λ μκ³ λ¦¬μ¦μ΄ μ λ§λ‘ μ νν λμΌν μ λ ₯μ μ¬μ©νκ³ μ νν λμΌν μΆλ ₯μ μμ±νλ λ§€μ° κ°λ¨ν μλ리μ€μμλ μ ν΅μ μΈ λΉ-μ λ€λ¦ μ λ΅μ΄ μΆ©λΆν μ μμ΅λλ€. λ€λ₯Έ μ λ ₯/μΆλ ₯ νμ μ λν λͺ νν νμμ±μ΄ μκ³ μ»΄νμΌ νμ νμ μμ μ±μ΄ μ€μν κ΄μ¬μ¬μΌ λλ§ μ λ€λ¦μ λμ νμμμ€.
- 곡ν΅μ±μ μν κΈ°λ³Έ μΈν°νμ΄μ€/ν΄λμ€ μ¬μ©: μ¬λ¬ `TInput` λλ `TOutput` νμ
μ΄ κ³΅ν΅λ νΉμ±μ΄λ λμμ 곡μ νλ κ²½μ°(μ: λͺ¨λ `IPaymentRequest`μ `TransactionId`κ° μλ κ²½μ°), μ΄μ λν κΈ°λ³Έ μΈν°νμ΄μ€λ μΆμ ν΄λμ€λ₯Ό μ μνμμμ€. μ΄λ₯Ό ν΅ν΄ μ λ€λ¦ μ λ΅μ νμ
μ μ½ μ‘°κ±΄(
where TInput : ICommonBase)μ μ μ©νμ¬ νμ νΉμμ±μ μ μ§νλ©΄μ κ³΅ν΅ λ‘μ§μ μμ±ν μ μμ΅λλ€. - μ€λ₯ μ²λ¦¬ νμ€ν: μ λ΅μ΄ μ€λ₯λ₯Ό λ³΄κ³ νλ μΌκ΄λ λ°©λ²μ μ μνμμμ€. μ΄λ `Result
` κ°μ²΄λ₯Ό λ°ννκ±°λ `StrategyContext` λλ νΈμΆ ν΄λΌμ΄μΈνΈκ° ν¬μ°©νκ³ μ°μνκ² μ²λ¦¬ν μ μλ νΉμ νκ³ μ λ¬Έμνλ μμΈλ₯Ό λμ§λ κ²μ ν¬ν¨ν μ μμ΅λλ€.
κ²°λ‘
μ λ΅ ν¨ν΄μ μ€λ«λμ μ μ°ν μννΈμ¨μ΄ λμμΈμ μ΄μμΌλ‘, μ μ κ°λ₯ν μκ³ λ¦¬μ¦μ κ°λ₯νκ² νμ΅λλ€. κ·Έλ¬λ μ λ€λ¦μ μμ©ν¨μΌλ‘μ¨ μ°λ¦¬λ μ΄ ν¨ν΄μ μλ‘μ΄ μμ€μ κ²¬κ³ ν¨μΌλ‘ λμ΄μ¬λ¦½λλ€: μ λ€λ¦ μ λ΅ ν¨ν΄μ μκ³ λ¦¬μ¦ μ ν νμ μμ μ±μ 보μ₯ν©λλ€. μ΄ ν₯μμ λ¨μ§ νλ¬Έμ μΈ κ°μ μ΄ μλλΌ, νλμ μ΄κ³ μ μΈκ³μ μΌλ‘ λΆμ°λ μννΈμ¨μ΄ μμ€ν μ λν μ€μν μν€ν μ²μ κ³ λ €μ¬νμ λλ€.
μ»΄νμΌ νμμ μ νν νμ κ³μ½μ κ°μ ν¨μΌλ‘μ¨, μ΄ ν¨ν΄μ 무μν λ°νμ μ€λ₯λ₯Ό λ°©μ§νκ³ , μ½λ λͺ νμ±μ ν¬κ² ν₯μμν€λ©°, μ μ§λ³΄μλ₯Ό κ°μνν©λλ€. λ€μν μ§λ¦¬μ μ§μ, λ¬Ένμ λ§₯λ½, κ·μ νκ²½μ κ±Έμ³ μ΄μλλ μ‘°μ§μκ², νΉμ μκ³ λ¦¬μ¦μ΄ μλλ λ°μ΄ν° νμ κ³Ό μνΈμμ©νλλ‘ λ³΄μ₯λλ μμ€ν μ ꡬμΆνλ λ₯λ ₯μ λ§€μ° μ€μν©λλ€. νμ§νλ μΈκΈ κ³μ° λ° λ€μν κ²°μ ν΅ν©μμλΆν° 볡μ‘ν λ°μ΄ν° μ ν¨μ± κ²μ¬ νμ΄νλΌμΈμ μ΄λ₯΄κΈ°κΉμ§, μ λ€λ¦ μ λ΅ ν¨ν΄μ κ°λ°μκ° νλ€λ¦¬μ§ μλ μμ κ°μ κ°μ§κ³ κ°λ ₯νκ³ , νμ₯ κ°λ₯νλ©°, μ μΈκ³μ μΌλ‘ μ μ κ°λ₯ν μ ν리μΌμ΄μ μ λ§λ€ μ μλλ‘ μ§μν©λλ€.
μ μ°νκ³ ν¨μ¨μ μΌ λΏλ§ μλλΌ λ³Έμ§μ μΌλ‘ λ μμ νκ³ μ λ’°ν μ μλ μμ€ν μ ꡬμΆνκΈ° μν΄ μ λ€λ¦ μ λ΅μ νμ λ°μλ€μ΄μμμ€. μ§μ ν κΈλ‘λ² λμ§νΈ μΈκ³μ 볡μ‘ν μꡬλ₯Ό μΆ©μ‘±μν¬ μ€λΉκ° λ μμ€ν μ λ§μ λλ€.